#pragma once

#include <functional>

#include "TaskBase.h"
#include "Schedule.h"

//class ISchedule;


template<typename ReultType>
class CTask: public CTaskBase
{
public:
    using FunctionType=std::function<ReultType(bool& /*out succeed*/)>;
    using RawFunctionType = ReultType(*)(bool& /*out succeed*/);

    CTask(ISchedule* InSchedule,const FunctionType & InFun)
    {
        this->Schedule=InSchedule;
        Fun=InFun;
        State.store(CTaskBase::EState::JustCreated);
    }

    //右值引用版本
    CTask(ISchedule* InSchedule,FunctionType && InFun)
    {
        this->Schedule=InSchedule;
        Fun=std::move(InFun);
        State.store(CTaskBase::EState::JustCreated);
    }

    //raw pointer version
    CTask(ISchedule* InSchedule,RawFunctionType InFun)
    {
        this->Schedule=InSchedule;
        Fun=InFun;
        State.store(CTaskBase::EState::JustCreated);
    }

    bool Do() override
    {
        bool bSucceed=true;
        ResultData=Fun(bSucceed);

        if(bSucceed)
        {
            State.store(CTaskBase::EState::Finished);
        }
        else
        {
            State.store(CTaskBase::EState::Failed);
        }

        return bSucceed;
    }

    bool IsFinished() const override
    {
        return State.load() == CTaskBase::EState::Finished;
    }

    bool IsJustCreated() const
    {
        return State.load() == CTaskBase::EState::JustCreated;
    }

    void PutIntoScheduleIfJustCreated()
    {
        if(IsJustCreated())
        {
            Schedule->AddTask(this->AsShared());
        }
    }

    // const ReultType & GetResult() const
    // {
    //     return this->ResultData;
    // }

    ReultType & GetResult()
    {
        return this->ResultData;
    }
protected:
    FunctionType Fun;

    ReultType ResultData;

};



template<>
class CTask<void>: public CTaskBase 
{
public:
    using FunctionType=std::function<void(bool& /*out succeed*/ )>;
    using RawFunctionType = void(*)(bool& /*out succeed*/ );

    CTask(ISchedule* InSchedule, const FunctionType & InFun)
    {
        this->Schedule=InSchedule;
        Fun=InFun;
        State.store(CTaskBase::EState::JustCreated);
    }

    //右值引用版本
    CTask(ISchedule* InSchedule, FunctionType && InFun)
    {
        this->Schedule=InSchedule;
        Fun=std::move(InFun);
        State.store(CTaskBase::EState::JustCreated);
    }

    //raw pointer version
    CTask(ISchedule* InSchedule, RawFunctionType InFun)
    {
        this->Schedule=InSchedule;
        Fun=InFun;
        State.store(CTaskBase::EState::JustCreated);
    }

    bool Do() override
    {
        bool bSucceed=true;
        Fun(bSucceed);

        if(bSucceed)
        {
            State.store(CTaskBase::EState::Finished);
        }
        else
        {
            State.store(CTaskBase::EState::Failed);
        }

        return bSucceed;
    }

    bool IsFinished() const override
    {
        return State.load() == CTaskBase::EState::Finished;
    }

    bool IsJustCreated() const override
    {
        return State.load() == CTaskBase::EState::JustCreated;
    }

    void PutIntoScheduleIfJustCreated()
    {
        if(IsJustCreated())
        {
            this->Schedule->AddTask(this->AsShared());
        }
    }
protected:
    FunctionType Fun;

};


